package plugins.order;

import kd.bos.base.BaseShowParameter;
import kd.bos.bill.AbstractBillPlugIn;
import kd.bos.dataentity.OperateOption;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.metadata.IDataEntityProperty;
import kd.bos.datamodel.model.validator.ValidateResult;
import kd.bos.entity.datamodel.IDataModel;
import kd.bos.entity.operate.OperateOptionConst;
import kd.bos.entity.operate.result.IOperateInfo;
import kd.bos.entity.operate.result.OperationResult;
import kd.bos.exception.KDBizException;
import kd.bos.form.ShowType;
import kd.bos.form.StyleCss;
import kd.bos.form.control.Control;
import kd.bos.form.control.Toolbar;
import kd.bos.form.control.events.ItemClickEvent;
import kd.bos.form.events.AfterDoOperationEventArgs;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.operation.OperationServiceHelper;
import kd.bos.servicehelper.QueryServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.bos.xdb.sharding.sql.PropertyInfo;
import kd.sdk.plugin.Plugin;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.EventObject;
import java.util.List;

import static kd.bos.login.utils.LoginUtils.logger;

public class checkBySchoolCard extends AbstractBillPlugIn implements Plugin {

    private static final String TIME_FIELD = "dcb4_time"; // 时间字段标识
    private static final String DATE_FIELD = "dcb4_date"; // 新增日期字段标识

    @Override
    public void itemClick(ItemClickEvent evt) {
        super.itemClick(evt);

        if ("dcb4_byschoolcard".equals(evt.getItemKey())) {
            // 1. 获取当前单据字段值
            DynamicObject currentUser = (DynamicObject) this.getModel().getValue("dcb4_user");
            BigDecimal currentAmount = (BigDecimal) this.getModel().getValue("dcb4_amount_sum");
            DynamicObject merchant = (DynamicObject) this.getModel().getValue("dcb4_merchant");

            if (currentUser == null || currentAmount == null || merchant == null) {
                this.getView().showTipNotification("请先填写用户、商户和金额！");
                return;
            }

            // 2. 查询校园卡数据
            String targetEntityId = "dcb4_schoolcard";
            QFilter userFilter = new QFilter("dcb4_user", "=", currentUser.getPkValue());

            DynamicObjectCollection targetBills = QueryServiceHelper.query(
                    targetEntityId,
                    "id,dcb4_amount,number,dcb4_status",
                    new QFilter[]{userFilter},
                    "id desc",
                    1
            );

            if (targetBills == null || targetBills.isEmpty()) {
                this.getView().showTipNotification("未找到关联的校园卡数据！");
                return;
            }

            DynamicObject targetBill = targetBills.get(0);

            // 3. 新增：检查校园卡状态
            String cardStatus = targetBill.getString("dcb4_status");
            if ("C".equals(cardStatus)) { // 状态为锁定
                this.getView().showTipNotification("校园卡已锁定，请检查账户状态！");
                return; // 直接返回不执行后续操作
            }


            BigDecimal targetAmount = targetBill.getBigDecimal("dcb4_amount");
            int result = currentAmount.compareTo(targetAmount);
            String message = result > 0 ? "当前金额大于校园卡金额" :
                    result < 0 ? "当前金额小于校园卡金额" : "金额相等";
            // this.getView().showTipNotification(message);

            // 4. 当金额小于校园卡金额时，自动生成历史记录
            if (result < 0) {

                // 6. 临时解锁当前单据的时间和日期字段
                this.getView().setEnable(true, TIME_FIELD);
                this.getView().setEnable(true, DATE_FIELD);

                // 获取当前时间的小时、分钟、秒
                Calendar calendar = Calendar.getInstance();
                int hour = calendar.get(Calendar.HOUR_OF_DAY);   // 当前小时（24小时制）
                int minute = calendar.get(Calendar.MINUTE);     // 当前分钟
                int second = calendar.get(Calendar.SECOND);     // 当前秒

                //获取当前日期
                int year = calendar.get(Calendar.YEAR);
                int month = calendar.get(Calendar.MONTH) + 1; // 月份从0开始，所以需要加1
                int day = calendar.get(Calendar.DAY_OF_MONTH); // 当前日

                // 写入日期字段（只保留年月日部分）
                this.getModel().setValue(DATE_FIELD, String.format("%04d-%02d-%02d", year, month, day));

                // 计算从当天零点到当前时间的总秒数
                int totalSeconds = hour * 3600 + minute * 60 + second;

                // 写入时间字段（单据头字段）
                this.getModel().setValue(TIME_FIELD, totalSeconds);

                // 立即锁定字段
                this.getView().setEnable(false, TIME_FIELD);
                this.getView().setEnable(false, DATE_FIELD);

                // 刷新界面显示
                this.getView().updateView(TIME_FIELD);

                createCardHistoryRecord(currentUser, currentAmount, merchant, targetBill);

                // 5. 更新校园卡余额
                updateSchoolCardBalance();

            } else if (result > 0) {
                // 金额大于校园卡金额时，提示用户
                this.getView().showTipNotification("余额不足，请使用其他支付方式或充值校园卡！");
            }
        }
    }

    /**
     * 更新校园卡余额
     */

    public void updateSchoolCardBalance() {
        try {
            // 1. 获取当前单据值
            DynamicObject userObj = (DynamicObject) this.getModel().getValue("dcb4_user");
            BigDecimal amountSum = (BigDecimal) this.getModel().getValue("dcb4_amount_sum");

            if (userObj == null || amountSum == null) {
                this.getView().showTipNotification("用户或金额为空！");
                return;
            }

            Long userId = (Long) userObj.getPkValue();

            // 2. 查询目标基础资料
            QFilter userFilter = new QFilter("dcb4_user", "=", userId);
            DynamicObject schoolCard = BusinessDataServiceHelper.loadSingle(
                    "dcb4_schoolcard",
                    "id,dcb4_amount",
                    new QFilter[]{userFilter}
            );

            if (schoolCard == null) {
                this.getView().showTipNotification("未找到对应的校园卡记录！");
                return;
            }

            // 3. 计算并更新金额
            BigDecimal currentAmount = schoolCard.getBigDecimal("dcb4_amount");
            BigDecimal newAmount = currentAmount.subtract(amountSum);

            // 金额非负校验
            if (newAmount.compareTo(BigDecimal.ZERO) < 0) {
                this.getView().showErrorNotification("校园卡余额不足！");
                return;
            }

            schoolCard.set("dcb4_amount", newAmount);

            // 4. 关键步骤：执行保存操作（根据文档内容添加）
            OperateOption option = OperateOption.create();
            // 绕过审核锁定（根据文档《230-数据保存服务.md》）
            option.setVariableValue("ignoreApprovedStatus", "true");

            OperationResult result = OperationServiceHelper.executeOperate(
                    "save",
                    "dcb4_schoolcard",
                    new DynamicObject[]{schoolCard},
                    option
            );

            if (result.isSuccess()) {
                // this.getView().showSuccessNotification("校园卡余额更新成功，新的余额为：" + newAmount);
            } else {
                this.getView().showErrorNotification("更新失败：" + result.getMessage());
            }

        } catch (Exception e) {
            this.getView().showErrorNotification("系统错误：" + e.getMessage());
        }
    }

    /**
     * 创建校园卡历史记录
     */
    private void createCardHistoryRecord(DynamicObject user, BigDecimal amount, DynamicObject merchant, DynamicObject schoolCard) {
        try {
            // 1. 创建新的历史记录单据
            DynamicObject newHistory = BusinessDataServiceHelper.newDynamicObject("dcb4_cardhistory");

            // 2. 设置校园卡基础资料字段
            String numberValue = schoolCard.getString("number");
            QFilter filter = new QFilter("number", QFilter.equals, numberValue);
            DynamicObject[] schoolCards = BusinessDataServiceHelper.load(
                    "dcb4_schoolcard",
                    "id",
                    new QFilter[]{filter}
            );

            if (schoolCards != null && schoolCards.length > 0) {
                newHistory.set("dcb4_schoolcard", schoolCards[0].getPkValue());
            }

            // 3. 设置其他字段
            newHistory.set("dcb4_merchant", merchant);
            newHistory.set("dcb4_amount", amount);

            // 4. 调用日期时间锁定方法
            performCheckIn(newHistory);

            // 5. 设置单据状态为暂存（A）
            newHistory.set("billstatus", "A");

            // 6. 保存单据
            OperationResult saveResult = SaveServiceHelper.saveOperate(
                    "dcb4_cardhistory",
                    new DynamicObject[]{newHistory},
                    OperateOption.create()
            );

            if (!saveResult.isSuccess()) {
                handleOperationError("保存失败", saveResult);
                return;
            }

            // 7. 获取保存成功的单据ID
            List<Object> successPkIds = saveResult.getSuccessPkIds();
            if (successPkIds == null || successPkIds.isEmpty()) {
                this.getView().showTipNotification("历史记录保存成功，但未获取到单据ID");
                return;
            }

            // 8. 准备操作选项（跳过交互提示）
            OperateOption submitOption = OperateOption.create();
            submitOption.setVariableValue(OperateOptionConst.IGNOREINTERACTION, "true");
            submitOption.setVariableValue(OperateOptionConst.IGNOREWARN, "true");

            // 9. 执行提交操作
            OperationResult submitResult = OperationServiceHelper.executeOperate(
                    "submit",
                    "dcb4_cardhistory",
                    successPkIds.toArray(),
                    submitOption
            );

            if (!submitResult.isSuccess()) {
                handleOperationError("提交失败", submitResult);
                return;
            }

            // 10. 准备审核选项
            OperateOption auditOption = OperateOption.create();
            auditOption.setVariableValue(OperateOptionConst.IGNOREINTERACTION, "true");
            auditOption.setVariableValue(OperateOptionConst.IGNOREWARN, "true");

            // 11. 执行审核操作
            OperationResult auditResult = OperationServiceHelper.executeOperate(
                    "audit",
                    "dcb4_cardhistory",
                    successPkIds.toArray(),
                    auditOption
            );

            if (!auditResult.isSuccess()) {
                handleOperationError("审核失败", auditResult);
            } else {
                // this.getView().showSuccessNotification("历史记录已成功保存、提交并审核");
                saveandsubmitCurrentBill();
            }

        } catch (Exception e) {
            this.getView().showErrorNotification("创建历史记录时出错：" + e.getMessage());
        }
    }

    public void saveandsubmitCurrentBill() {
        // 创建操作选项并禁用消息提示
        OperateOption saveOption = OperateOption.create();
        saveOption.setVariableValue(OperateOptionConst.ISSHOWMESSAGE, "false");

        // 执行保存操作（禁用提示）
        this.getView().invokeOperation("save", saveOption);

        OperateOption submitOption = OperateOption.create();
        submitOption.setVariableValue(OperateOptionConst.ISSHOWMESSAGE, "false");

        this.getView().invokeOperation("submit", submitOption);
    }


    // 修改后的日期时间锁定方法（接受单据对象）
    private void performCheckIn(DynamicObject historyBill) {
        // 1. 写入时间字段
        Calendar calendar = Calendar.getInstance();
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);
        int second = calendar.get(Calendar.SECOND);
        int totalSeconds = hour * 3600 + minute * 60 + second;
        historyBill.set("dcb4_time", totalSeconds);

        // 2. 写入日期字段
        Calendar dateOnly = Calendar.getInstance();
        dateOnly.set(Calendar.HOUR_OF_DAY, 0);
        dateOnly.set(Calendar.MINUTE, 0);
        dateOnly.set(Calendar.SECOND, 0);
        dateOnly.set(Calendar.MILLISECOND, 0);
        historyBill.set("dcb4_date", dateOnly.getTime());
    }

    /**
     * 处理操作错误
     *
     * @param operationName 操作名称
     * @param result 操作结果
     */
    private void handleOperationError(String operationName, OperationResult result) {
        StringBuilder errorMsg = new StringBuilder(operationName);

        // 获取所有错误信息
        for (IOperateInfo errorInfo : result.getAllErrorOrValidateInfo()) {
            errorMsg.append("\n- ").append(errorInfo.getMessage());

            // 获取关联字段信息（如果有）
            if (errorInfo instanceof ValidateResult) {
                ValidateResult validateResult = (ValidateResult) errorInfo;
                if (validateResult.getResultItems() != null) {
                    errorMsg.append(" (字段: ").append(validateResult.getResultItems().stream().toArray()).append(")");
                }
            }
        }

        this.getView().showErrorNotification(errorMsg.toString());
    }

}